/** @jsxImportSource @emotion/react */
/*临时使用的，等待底层组件集成进去*/
import {  css, SerializedStyles } from "@emotion/react";
import * as React from "react";
//import { Text, LabelText } from "./Text";
//import VisuallyHidden from "@reach/visually-hidden";
import PropTypes, {string} from "prop-types";
//import { alpha } from "./Theme/colors";
import { alpha } from "customize-easy-ui-component/esm/Theme/colors";
//import { useUid } from "./Hooks/use-uid";
import { useUid } from "customize-easy-ui-component/esm/Hooks/use-uid";
//import { Theme } from "./Theme";
//import { useTheme } from "./Theme/Providers";
//import {getHeight, focusShadow, ButtonSize} from "./Button";
//import { IconAlertCircle, IconChevronDown } from "./Icons";
//mport { safeBind } from "./Hooks/compose-bind";
import { safeBind } from "customize-easy-ui-component/esm/Hooks/compose-bind";
import { useMedia } from "use-media";
import  Switch from "react-switch";
import {MutableRefObject, useCallback, useEffect, useState} from "react";
import {
    useTheme,
    VisuallyHidden,
    IconAlertCircle, IconChevronDown,
    getHeight, focusShadow, ButtonSize,
    Text, LabelText,
    Theme
} from "customize-easy-ui-component";



/*
自适应布局，容器父组件不应当设置width固定的px，否则内部组件元素{已经为屏幕宽度自适应适配的组件}都会被动拉伸宽度，失去了效果。
*/

const getInputSizes = (theme: Theme) => ({
    sm: css({
        fontSize: theme.fontSizes[0],
        padding: "0.25rem 0.5rem"
    }),
    md: css({
        fontSize: theme.fontSizes[1],
        padding: "0.5rem 0.75rem"
    }),
    lg: css({
        fontSize: theme.fontSizes[2],
        padding: "0.65rem 1rem"
    })
});

export type InputSize = "sm" | "md" | "lg";

export interface InputGroupProps extends React.HTMLAttributes<HTMLDivElement> {
    id?: string;
    /** A label is required for accessibility purposes. Use `hideLabel` to hide it. */
    label: string;
    /** Visually hide the label. It remains accessible to screen readers. */
    hideLabel?: boolean;
    error?: string | React.ReactNode;
    /** Optional help text */
    helpText?: string;
    /** A single input element */
    children?: React.ReactNode;
    labelStyle?: SerializedStyles;
    labelTextStyle?: SerializedStyles;
}

interface InputGroupContextType {
    uid?: string;
    error?: string | React.ReactNode;
}

const InputGroupContext = React.createContext<InputGroupContextType>({
    uid: undefined,
    error: undefined
});
/**
 原来版本的输入分组项目；    新版本使用InputLine
 */
export const InputGroup: React.FunctionComponent<InputGroupProps> = ({
                                                                         id,
                                                                         label,
                                                                         children,
                                                                         error,
                                                                         helpText,
                                                                         hideLabel,
                                                                         labelStyle,
                                                                         labelTextStyle,
                                                                         ...other
                                                                     }) => {
    const uid = useUid(id);
    const theme = useTheme();
    const isDark = theme.colors.mode === "dark";
    const danger = isDark
        ? theme.colors.intent.danger.light
        : theme.colors.intent.danger.base;

    return (
        <section
            className="InputGroup"
            css={{
                marginTop: theme.spaces.md,
                "&.InputGroup:first-of-type": {
                    marginTop: 0
                }
            }}
            {...other}
        >
            <Label hide={hideLabel} htmlFor={uid} css={labelStyle} textStyle={labelTextStyle} >
                {label}
            </Label>
            <InputGroupContext.Provider
                value={{
                    uid,
                    error
                }}
            >
                {children}
            </InputGroupContext.Provider>

            {error && typeof error === "string" ? (
                <div
                    className="InputGroup__error"
                    css={{
                        alignItems: "center",
                        marginTop: theme.spaces.sm,
                        display: "flex"
                    }}
                >
                    <IconAlertCircle size="sm" color={danger} />
                    <Text
                        css={{
                            display: "block",
                            marginLeft: theme.spaces.xs,
                            fontSize: theme.fontSizes[0],
                            color: danger
                        }}
                    >
                        {error}
                    </Text>
                </div>
            ) : (
                error
            )}

            {helpText && (
                <Text
                    className="InputGroup__help"
                    css={{
                        display: "block",
                        marginTop: theme.spaces.xs,
                        color: theme.colors.text.muted,
                        fontSize: theme.fontSizes[0]
                    }}
                    variant="body"
                >
                    {helpText}
                </Text>
            )}
        </section>
    );
};

InputGroup.propTypes = {
    label: PropTypes.string.isRequired,
    hideLabel: PropTypes.bool,
    helpText: PropTypes.string,
    error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
    id: PropTypes.string,
    children: PropTypes.element
};

function shadowBorder(color: string, opacity: number) {
    return `0 0 0 2px transparent inset, 0 0 0 1px ${alpha(
        color,
        opacity
    )} inset`;
}

function getBaseStyles(theme: Theme) {
    const dark = theme.colors.mode === "dark";

    const baseStyles = css({
        display: "block",
        width: "100%",
        lineHeight: theme.lineHeights.body,
        color: theme.colors.text.default,
        backgroundColor: "transparent",
        backgroundImage: "none",
        backgroundClip: "padding-box",
        WebkitFontSmoothing: "antialiased",
        WebkitTapHighlightColor: "transparent",
        WebkitAppearance: "none",
        boxSizing: "border-box",
        touchAction: "manipulation",
        fontFamily: theme.fonts.base,
        border: "none",
        boxShadow: dark
            ? shadowBorder(theme.colors.palette.gray.lightest, 0.14)
            : shadowBorder(theme.colors.palette.gray.dark, 0.2),
        borderRadius: theme.radii.sm,
        transition:
            "background 0.25s cubic-bezier(0.35,0,0.25,1), border-color 0.15s cubic-bezier(0.35,0,0.25,1), box-shadow 0.15s cubic-bezier(0.35,0,0.25,1)",
        "::placeholder": {
            color: alpha(theme.colors.text.default, 0.45)
        },
        ":focus": {
            boxShadow: dark
                ? focusShadow(
                    alpha(theme.colors.palette.blue.light, 0.5),
                    alpha(theme.colors.palette.gray.dark, 0.4),
                    alpha(theme.colors.palette.gray.light, 0.2)
                )
                : focusShadow(
                    alpha(theme.colors.palette.blue.dark, 0.1),
                    alpha(theme.colors.palette.gray.dark, 0.2),
                    alpha(theme.colors.palette.gray.dark, 0.05)
                ),
            outline: "none"
        },
        ":disabled": {
            opacity: dark ? 0.4 : 0.8,
            background: theme.colors.background.tint1,
            cursor: "not-allowed",
            boxShadow: dark
                ? shadowBorder(theme.colors.palette.gray.lightest, 0.15)
                : shadowBorder(theme.colors.palette.gray.dark, 0.12)
        },
        ":active": {
            background: theme.colors.background.tint1
        }
    });

    return baseStyles;
}

function useActiveStyle() {
    const [active, setActive] = React.useState(false);
    return {
        bind: {
            onTouchStart: () => setActive(true),
            onTouchEnd: () => setActive(false)
        },
        active
    };
}

function useSharedStyle() {
    const theme = useTheme();
    const errorStyles = {
        boxShadow: shadowBorder(theme.colors.intent.danger.base, 0.45)
    };

    const baseStyles = React.useMemo(() => getBaseStyles(theme), [theme]);
    const inputSizes = React.useMemo(() => getInputSizes(theme), [theme]);
    const activeBackground = css({ background: theme.colors.background.tint1 });
    return {
        baseStyles,
        inputSizes,
        activeBackground,
        errorStyles
    };
}

export interface InputRefBaseProps
    extends React.InputHTMLAttributes<HTMLInputElement> {
    /** The size of the input element */
    inputSize?: InputSize;
    //topDivStyle?: SerializedStyles;
    value?: string | number;
    //onSave: (text: string) => void;
}

/**
 * Our basic Input element. Use this when building customized
 * forms. Otherwise, stick with InputGroup
 * 原先InputBase 改名成 InputRefBase; 比如ComboBox才会需要使用forwardRef形式的;
 */

export const InputRefBase = React.forwardRef(
    (
        { autoComplete, autoFocus, inputSize = "md", ...other }: InputRefBaseProps,
        ref: React.Ref<HTMLInputElement>
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        return (
            <input
                id={uid}
                className="Input"
                autoComplete={autoComplete}
                autoFocus={autoFocus}
                {...bind}
                css={[
                    baseStyles,
                    inputSizes[inputSize],
                    active && activeBackground,
                    error && errorStyles,
                    { height }
                ]}
                {...safeBind({ ref }, other)}
            />
        );
    }
);

export interface InputBaseProps
    extends React.InputHTMLAttributes<HTMLInputElement> {
    /** The size of the input element */
    inputSize?: InputSize;
    //topDivStyle?: SerializedStyles;
    value?: string | number;
    onSave: (text: string) => void;
}
/**InputBase要求一次性触发变更， 对比Input是onChange每次点击键盘按键都会变更。
 * 正常都不需要使用forwardRef形式的，可大大地加快速度。 InputRefBase是ref版本;
 * 性能优化，去掉了React.forwardRef 改成React.FunctionComponent
 * InputSimple普通FunctionComponent代替React.forwardRef(safeBind({ ref }就能从365ms变240ms啦。
 *InputBase目前只由SuffixInput引用到；
 */
export const InputBase: React.FunctionComponent<InputBaseProps>=
    (
        {
            autoComplete,
            autoFocus,
            inputSize = "md",
            value,
            onSave,
            ...other
        }
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        const commitChanges = (e :any) => {
            if (e.target.value !== value) {
                onSave(e.target.value as any);
            }
        };
        const handleBlur = (e :any) => {
            commitChanges(e);
        };
        const handleKeyDown = (e :any) => {
            if (e.keyCode === ENTER_KEY_CODE) {
                commitChanges(e);
            }
            else if (e.keyCode === ESC_KEY_CODE) {
                e.target.value= value;
            }
        };
        return (
            <input
                id={uid}
                className="Input"
                autoComplete={autoComplete}
                autoFocus={autoFocus}
                {...bind}
                css={[
                    baseStyles,
                    inputSizes[inputSize],
                    active && activeBackground,
                    error && errorStyles,
                    { height }
                ]}
                defaultValue={value}
                onBlur={handleBlur}
                onKeyDown={handleKeyDown}
                {...other}
            />
        );
    };


InputBase.propTypes = {
    inputSize: PropTypes.oneOf(["sm", "md", "lg"] as InputSize[]),
    autoComplete: PropTypes.string,
    autoFocus: PropTypes.bool
};


export interface InputProps 　 extends InputRefBaseProps {
    /** 控制是否满上宽度;
     *  需要在<input> 上 去控制大尺寸上限的width:  ，以及自适应屏幕大小后的 max-width: 缩小尺寸。
     * */
    fullWidth?: boolean;
}

/**
 * Input 比起InputBase，外面多包裹一个div以便于控制宽度和对齐。
 * 需要传递ref的，请使用 InputRefComp 替换。
 * style是父辈注入的样式: 父辈采用React.cloneElement(children, { style: {flex: '1 1 60%' } }注入样式。
 */
export const Input: React.FunctionComponent<InputProps> =
    (
        {
            autoComplete, autoFocus,
            inputSize = "md",
            fullWidth=true,
            style,
            ...other
        }
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);

        return (
            <div  css={{
                textAlign: 'left',
                width: "100%",
                ...style
            }}
            >
                <input
                    id={uid}
                    className="Input"
                    autoComplete={autoComplete}
                    autoFocus={autoFocus}
                    {...bind}
                    css={[
                        baseStyles,
                        inputSizes[inputSize],
                        active && activeBackground,
                        error && errorStyles,
                        { height },
                        !fullWidth &&{
                            width: 'unset',
                        }
                    ]}
                    {...other}
                />
            </div>
        );
    };

/**
 * InputRefComp 是ref传递版本的 Input ,特别情况用
 * InputRefComp 比起 InputRefBase多个一层<div>可以注入控制样式,外面多包裹一个div以便于控制宽度和对齐。。
 */
export const InputRefComp = React.forwardRef(
    (
        { autoComplete, autoFocus, inputSize = "md",
            fullWidth=true,
            style,
            ...other }: InputProps,
        ref: React.Ref<HTMLInputElement>
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        return (
            <div  css={
                {
                    textAlign: 'left',
                    width: "100%",
                    ...style
                }
            }
            >
                <input
                    id={uid}
                    className="Input"
                    autoComplete={autoComplete}
                    autoFocus={autoFocus}
                    {...bind}
                    css={[
                        baseStyles,
                        inputSizes[inputSize],
                        active && activeBackground,
                        error && errorStyles,
                        { height },
                        !fullWidth &&{
                            width: 'unset',
                        }
                    ]}
                    {...safeBind({ ref }, other)}
                />
            </div>
        );
    }
);

//export const Input = InputBase;   直接替换

export interface TextAreaProps
    extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
    /** The size of the textarea element */
    inputSize?: InputSize;
    //topDivStyle?: SerializedStyles;
}

/**
 * Textarea version of InputBase
 */

export const TextArea: React.FunctionComponent<TextAreaProps> = (
    {
        inputSize = "md",
        style,
        ...other
    }) => {
    const { bind, active } = useActiveStyle();
    const {
        baseStyles,
        inputSizes,
        activeBackground,
        errorStyles
    } = useSharedStyle();
    const { uid, error } = React.useContext(InputGroupContext);

    return (
        <textarea
            className="TextArea"
            id={uid}
            {...bind}
            css={[
                baseStyles,
                inputSizes[inputSize],
                {
                    overflow: "auto",
                    resize: "vertical",
                },
                active && activeBackground,
                error && errorStyles,
                {...style}
            ]}
            {...other}
        />
    );
};

TextArea.propTypes = {
    inputSize: PropTypes.oneOf(["sm", "md", "lg"] as InputSize[])
};



export interface LabelProps
    extends React.LabelHTMLAttributes<HTMLLabelElement> {
    hide?: boolean;
    htmlFor: string;
    textStyle?: SerializedStyles;
}

/**
 * A styled Label to go along with input elements
 */

export const Label: React.FunctionComponent<LabelProps> = ({
                                                               children,
                                                               hide,
                                                               textStyle,
                                                               ...other
                                                           }) => {
    const theme = useTheme();
    const child = (
        <label
            className="Label"
            css={{
                display: "inline-block",
                marginBottom: hide ? 0 : theme.spaces.sm
            }}
            {...other}
        >
            <Text className="Label__text" variant={"subtitle"} css={textStyle}>
                {children}
            </Text>
        </label>
    );

    return hide ? <VisuallyHidden>{child}</VisuallyHidden> : child;
};

Label.propTypes = {
    hide: PropTypes.bool,
    children: PropTypes.element
};



export interface SelectProps
    extends React.SelectHTMLAttributes<HTMLSelectElement> {
    /** The size of the select box */
    inputSize?: InputSize;
    //内部第二层的Div的样式
    divStyle?: SerializedStyles;
    //topDivStyle?: SerializedStyles;
}

/**
 * multiple在手机上可以不展开列表了，但是选择2个以上在编辑框上面只能显示数目，不会显示选择那些必须点击进入才能看见。在电脑上面还是列表全部展开的形式。
 * 若multiple=true 导致直接拉开了，样式窗口高度都改变，失去UI一致性了『感觉不友好啊』。
 * 光光靠w3c标准也行不通, 难以通用，必须自己定制。
 * ComboBox不允许multiple；但是Select不允许自主添加新的列表项目，Select允许列表附加label描述文字代替value;
 * 若触摸屏 不能支持multiple形态的的Select，只能单选。?浏览器版本升级，但是还会有返回的数据【】集合机制问题,value=[values1,2]。
 * multiple 只是摊开选择列表，onChange  .target.value无法提供多选数组，必须额外维护可以多选的被选中状态和数据数组。
 * 原来版本是用这样复制 children 的这个 <option></option> 也能够用...other直接复制<select 的底下标签去。
 * style?: React.CSSProperties;
 */

export const Select: React.FunctionComponent<SelectProps> = (
    {
        multiple,
        inputSize = "md",
        divStyle,
        style,
        ...other
    }) => {
    const theme = useTheme();
    const inputSizes = getInputSizes(theme);
    const { uid, error } = React.useContext(InputGroupContext);
    const selectSize = {
        sm: inputSizes.sm,
        md: inputSizes.md,
        lg: inputSizes.lg
    };
    const dark = theme.colors.mode === "dark";
    const height = getHeight(inputSize);
    //因需要Select组件的max-width；导致Select若放InputGroupLine下在宽松模式一行内显示Label和Select的场景，在Select组件头层div设置宽度将会使得flex无法对齐两个项目；所以再套入一个div。
    //像这样<div style="border:dotted 2px black; background-color:Yellow;height:100px;" 是html底层样式表达法,实际无法实现注入的。
    //而styles=是变量名字。  style={{ padding: "0.43rem", textAlign: 'center' }}这是对象写法。
    //使用<div style={ style } 注入的将会是独立的style样式；调试开闭是只能针对单一个元素开关。
    //使用<div css={[style as any  注入的将会是class样式模组。调试开闭是可以开关多个相同class的元素。 两个模式都能有效果 style css。

    return (
        <div css={{
            textAlign: 'left',
            ...style
        }}
        >
            <div
                className="Select"
                css={[
                    {
                        //这个position: "relative"因为其下级的position: "absolute"定位的小小图标所约束。所以只能relative或sticky其他position取值不行。
                        position: "relative",
                    },
                    divStyle,
                ]}
            >
                <select
                    className="Select__input"
                    id={uid}
                    css={[
                        selectSize[inputSize],
                        {
                            WebkitAppearance: "none",
                            display: "block",
                            width: "100%",
                            // lineHeight: theme.lineHeights.body,
                            height: multiple? 'unset': height,
                            color: theme.colors.text.default,
                            background: "transparent",
                            fontFamily: theme.fonts.base,
                            boxShadow: `0 0 0 2px transparent inset, 0 0 0 1px ${
                                dark
                                    ? alpha(theme.colors.palette.gray.lightest, 0.14)
                                    : alpha(theme.colors.palette.gray.dark, 0.2)
                            } inset`,
                            border: "none",
                            backgroundClip: "padding-box",
                            borderRadius: theme.radii.sm,
                            margin: 0,
                            ":disabled": {
                                ":disabled": {
                                    opacity: dark ? 0.4 : 0.8,
                                    background: theme.colors.background.tint1,
                                    cursor: "not-allowed",
                                    boxShadow: `0 0 0 2px transparent inset, 0 0 0 1px ${
                                        dark
                                            ? alpha(theme.colors.palette.gray.lightest, 0.15)
                                            : alpha(theme.colors.palette.gray.dark, 0.12)
                                    } inset`
                                }
                            },
                            ":focus": {
                                borderColor: theme.colors.palette.blue.base,
                                boxShadow: dark
                                    ? focusShadow(
                                        alpha(theme.colors.palette.blue.light, 0.5),
                                        alpha(theme.colors.palette.gray.dark, 0.4),
                                        alpha(theme.colors.palette.gray.light, 0.2)
                                    )
                                    : focusShadow(
                                        alpha(theme.colors.palette.blue.dark, 0.1),
                                        alpha(theme.colors.palette.gray.dark, 0.2),
                                        alpha(theme.colors.palette.gray.dark, 0.05)
                                    ),
                                outline: 0
                            }
                        },
                        error && {
                            boxShadow: shadowBorder(theme.colors.intent.danger.base, 0.45)
                        }
                    ]}
                    multiple={multiple}
                    {...other}
                />
                {!multiple && (
                    <IconChevronDown
                        className="Select__icon"
                        color={theme.colors.text.muted}
                        css={{
                            position: "absolute",
                            top: "50%",
                            right: "0.75rem",
                            transform: "translateY(-50%)",
                            pointerEvents: "none"
                        }}
                    />
                )}
            </div>
        </div>
    );
};


Select.propTypes = {
    inputSize: PropTypes.oneOf(["sm", "md", "lg"]),
    multiple: PropTypes.bool
};




export interface CheckProps
    extends React.InputHTMLAttributes<HTMLInputElement> {
    /** A label for the checkmark. */
    label: string;
    //topDivStyle?: SerializedStyles;
}

export const Check: React.FunctionComponent<CheckProps> = (
    {
        label,
        id,
        disabled,
        style,
        ...other
    }) => {
    const uid = useUid(id);
    const theme = useTheme();

    return (
        <div  className="Check"
              css={[
                  {
                      display: "flex",
                      alignItems: "center",
                      ...style
                  }
              ]}
        >
            <input
                disabled={disabled}
                className="Check__input"
                type="checkbox"
                id={uid}
                css={[
                    {
                        height: '2rem',
                        width: '2rem',
                        display: 'inline-flex',
                        paddingLeft: '1rem',
                    },
                ]}
                {...other}
            />
            <label
                className="Check__label"
                css={{
                    opacity: disabled ? 0.6 : undefined,
                    marginLeft: theme.spaces.xs
                }}
                htmlFor={uid}
            >
                <Text>{label}</Text>
            </label>
        </div>
    );
};

Check.propTypes = {
    label: PropTypes.string.isRequired,
    id: PropTypes.string,
    disabled: PropTypes.bool
};

export interface InputPureProps
    extends React.InputHTMLAttributes<HTMLInputElement> {
    inputSize?: InputSize;
    value?: string | number;
}
/**最原始的input,没有div包裹;单个字符按键就触发
 * */
export const InputPure: React.FunctionComponent<InputPureProps>=
    (
        {
            autoComplete,
            autoFocus,
            inputSize = "md",
            ...other
        }
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        return (
            <input
                id={uid}
                className="Input"
                autoComplete={autoComplete}
                autoFocus={autoFocus}
                {...bind}
                css={[
                    baseStyles,
                    inputSizes[inputSize],
                    active && activeBackground,
                    error && errorStyles,
                    { height }
                ]}
                {...other}
            />
        );
    };


//带单位标注的输入框
export interface SuffixInputProps
    extends InputBaseProps {
    textStyle?: SerializedStyles;
    //可替换 前半部分的输入框组件
    component?: React.ElementType<any>;
}
export interface SuffixInputPureProps
    extends InputPureProps {
    textStyle?: SerializedStyles;
    //可替换 前半部分的输入框组件, 比如InputPure代替InputBase实现立刻更新;
    component?: React.ElementType<any>;
}
/** SuffixInput 带单位标注的输入框
 * A styled Label to go along with input elements
 * 若children有，就是有附带单位后缀串的模式；
 * 带单位后缀的说明，70%给输入框，后面30%给叙述单位字串{空格也算}
 * 输入的 单位说明 字符串 放在 <Text className="Suffix__text"  >
 * 没有ref注入的版本；
 */
export const SuffixInput: React.FunctionComponent<SuffixInputProps|SuffixInputPureProps> = (
    {
        children,
        textStyle,
        inputSize,
        component: Component =InputBase,
        style,
        ...other
    }
) => {
    //const theme = useTheme();
    //children可以是非字符串的, 按钮等。
    return (
        <div  css={
            {
                textAlign: 'left',
                //display: "inline-block",
                ...style
            }}
        >
            <Component inputSize={inputSize}
                       css={{
                           display: "inline-block",
                           width:  children? "70%" : '100%',
                       }}
                       {...other}
            />
            {typeof children === "string" ? (
                <Text className="Suffix__text" variant={"subtitle"}
                      css={[
                          {
                              display: children? "inline-flex" : 'none',
                              paddingLeft: '0.2rem'
                          },
                          textStyle
                      ]}
                >
                    {children}
                </Text>
            ) : (
                children
            )}
        </div>
    );
};

SuffixInput.propTypes = {
    children: PropTypes.element
};


export interface InputLineProps extends InputGroupProps {
    //对一整行的控制
    lineStyle?: SerializedStyles;
    //根据换行px数 ，来切换显示2个显示模式。 缺省>=360px 正常模式，否则紧凑模式。
    //switchPx?: number;
    //是否开启宽度紧凑模式的局部布局，意味着无法满足最小宽度要求了。
    fitable?: boolean;
}

/**
 自适应屏幕flexBox布局：不要设置固定的width和min-width，可以设置max-width；根据屏幕宽策划1列2列还是更多列的并列，或是更高层次嵌套或隐藏或显示一小半边天区域。
 不要对InputGroupLine的上一级div定义固定宽度，自适应和固定width: px只能二者选其一；宽度定了对小屏幕场景就有滚动条，而不是自适应缩小flexBox布局。
 修改InputGroup排版模式; 并排模式，根据屏幕自适应。支持 2 个模式的布局安排结构。
 性能优化，旧版本InputGroupLine=680ms; 新的InputLine=600ms;
 这两个布局占位参数 error, helpText感觉意义不大。
 InputGroupContext才是最关键的，子孙组件uid和LabelText标签挂接。

 一般<section>出现在文档文章大纲中。一般通过是否包含一个标题 <h1>-<h6>作为子节点 来辨识<section>。
 InputLine只能支持下面有唯一的一个儿子组件的。 可以使用<div>包裹多个孙子组件。 举例如下：
 <div>
 <Check label="Male" checked />
 <Check label="Female" />
 </div>
 儿子若这样<div style={{border: `1px solid ${theme.colors.border.default}`}} > 实际style就将无法起作用；
 儿子像这样<div style="border:dotted 2px black; background-color:Yellow;height:100px;" 实际将无法起作用。 style={css`margin: 1rem 2rem;`} > style={css({ padding: "1rem 2rem" })} >将无法起作用;
 儿子像这样<div css={css({ padding: "1rem 2rem" })}，这样 css={css`margin: 1rem 2rem;`} 就会生效启用样式。
 儿子组件第一个div或tag若像这样 <div css={{marginTop: 19,backgroundColor: 'red'}} > 就会生效启用样式。
 儿子组件<div css={{flex: '1 1 20%',backgroundColor: 'red'}} 本组件从父辈修改注入style: {flex: '1 1 60%' }就会覆盖掉儿子div的flex: '1 1 20%'的原本样式。React.cloneElement(child模式 替换了。
 总之: 儿子组件必须用css={}；第三方独立组件也许要在外边加一层次div来调整样式。
 InputLine是单个输入包裹组件，外部再多搞一层布局组件LineColumn来配合。
 */

export const InputLine: React.FunctionComponent<InputLineProps> = (
    {
        id,
        label,
        children,
        error,
        helpText,
        hideLabel,
        labelTextStyle,
        lineStyle,
        fitable=true,
        ...other
    }) => {
    const uid = useUid(id);
    const theme = useTheme();
    const isDark = theme.colors.mode === "dark";
    const danger = isDark
        ? theme.colors.intent.danger.light
        : theme.colors.intent.danger.base;



    //InputGroupLine包裹的下层的顶级组件的样式修改：下层顶级元素的display: block还算兼容可用; 但width: 100%影响较大。
    //topDivStyle方式： 会不被识别认得，底下的<div>不懂得该如何处理。
    //假如底下是div 加上 element.style {   flex: 1 1 60%;  }；
    const childNodeVar = (
        <InputGroupContext.Provider
            value={{
                uid,
                error
            }}
        >
            {
                //只能支持一个儿子的。 可以为底下的<div>自动添加样式。
                //style: { flex: '1 1 60%' },      左边的项目文字描述　40%　右边输入框(含单位字符)占用60%
                React.cloneElement(
                    React.Children.only(children) as React.ReactElement<any>,
                    {
                        ///topDivStyle: { flex: '1 1 60%' },
                        style: {flex: '1 1 60%' }
                    }
                )
            }
        </InputGroupContext.Provider>
    );

    //这里htmlFor={uid}，标签label 和 input很可能分别属于不同div底下的。
    //const titleVar = (        );
    const TitleVar= <LabelText className="Label__text"  htmlFor={uid}
                               css={[
                                   {
                                       //display: "inline-flex",
                                       textAlign: fitable? "right" : "left",
                                       flex: '1 1 40%',
                                       paddingRight: '0.8rem',
                                       marginBottom: hideLabel ? 0 : theme.spaces.sm,
                                       wordBreak: 'break-word'
                                   },
                                   labelTextStyle
                               ]}
    >
        {label}
    </LabelText>;

    //子孙的宽度没有固定px的，布局组件的子孙都是可在宽度上做自适应的。只有目标多少列排列是敲定固定的，也就是预期最大父窗口宽度场合可以安排最多几个列的元素。
    //布局子孙都是平等的，宽度都平均分配，预期高度在同一行排列也是均衡整齐或高度一致的，
    //输入Line组件的断线折腰宽度在布局组件上就的设置switchPx参数。
    //这外部还得搞个布局组件嵌套，布局组件来传递进来布局紧凑与否参数fitable。也就是遇到最小最小的父窗口宽度情形，在只安排单列元素场合下的，给输入Line组件紧凑提示。
    // checkParent(React.Children.only(children) as any);
    //上级组件注入的style样式，这里实际在 ...other所接纳了。 上一级控制本组件的第一层div或tag, 其它层次其它参数来控制样式。

    return (
        <div
            className="InputLine"
            css={{
                marginTop: theme.spaces.md,
                "&.InputLine:first-of-type": {
                    marginTop: 0
                },
                textAlign: 'center'
            }}
            {...other}
        >

            <div  css={[
                {
                    alignItems: "center",
                    justifyContent: "space-around",
                    display: "flex",
                    // flexWrap: 'wrap',
                    maxWidth: '950px',
                    margin: '0 auto',
                    paddingRight:  'unset',
                },
                lineStyle
            ]}
            >
                {hideLabel ? <VisuallyHidden>{ TitleVar }</VisuallyHidden>
                    : TitleVar }

                {fitable && childNodeVar }
            </div>

            {!fitable && childNodeVar }

            {error && typeof error === "string" ? (
                <div
                    className="InputGroup__error"
                    css={{
                        alignItems: "center",
                        marginTop: theme.spaces.sm,
                        display: "flex",
                        justifyContent: 'center'
                    }}
                >
                    <IconAlertCircle size="sm" color={danger} />
                    <Text
                        css={{
                            display: "block",
                            marginLeft: theme.spaces.xs,
                            fontSize: theme.fontSizes[0],
                            color: danger
                        }}
                    >
                        {error}
                    </Text>
                </div>
            ) : (
                error
            )}

            {helpText && (
                <Text
                    className="InputGroup__help"
                    css={{
                        display: "inline-flex",
                        marginTop: theme.spaces.xs,
                        color: theme.colors.text.muted,
                        fontSize: theme.fontSizes[0]
                    }}
                    variant="body"
                >
                    {helpText}
                </Text>
            )}
        </div>
    );
};


InputLine.propTypes = {
    label: PropTypes.string.isRequired,
    hideLabel: PropTypes.bool,
    helpText: PropTypes.string,
    error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
    id: PropTypes.string,
    children: PropTypes.element
};

export interface InputDatalistProps  extends React.InputHTMLAttributes<HTMLInputElement> {
    /** The size of the input element */
    inputSize?: InputSize;
    /** 控制是否满上宽度;
     *  需要在<input> 上 去控制大尺寸上限的width:  ，以及自适应屏幕大小后的 max-width: 缩小尺寸。
     * */
    fullWidth?: boolean;
    //已经知道的列表
    datalist?: any[];
    //为了和ComboBoxDatalist保证参数一致才引入的。 接替onChange(); 直接用底层onChange可行的
    onListChange: (value: string|undefined) => void;
    value?: string | number;
}

/**底层浏览器已经做了现成的支持ComboBox，何必自己再搞那么麻烦呢。
 * 直接用W3C浏览器提供的<datalist标签？list做关联id,来做组合输入框，代替ComboBox组件
 *<datalist id=""> 实际上可以脱离<input 而存在的，比如作为全局的不改动的<datalist集合放在一起。 管理？分离掉了；
 * 还是自己包含<datalist维护好了。
 * InputDatalist对比ComboBox组件的弱点1非空编辑不能点击就显示所有列表2手机上列表展开位置与窗口大小太矮了3<option的label与value都显示出来感觉不好。
 * ，但比ComboBox有个有优势：1能够记住当前用户输入用过的以后再用。
 * 不过一般输入完成后再做点击修改的概率也不大，手机版本显示区域太小问题以后浏览器版本可能改进的。
 若组件附带参数这样的<InputDatalist css={{flex: '1 1 80%'}} > 将会导致...other实际接收这里的样式参数，样式不会作用于第一个div的。
 若组件附带参数这样的<InputDatalist style={{flex: '1 1 80%',backgroundColor: "pink"}}> 实际第一个div或者...other位置不会获得任何样式，也就是说style={{是无效的。
 <InputDatalist style={{border: `1px solid ${theme.colors.border.default}`}} >  实际style就将无法起作用；
 <InputDatalist style="border:dotted 2px black; background-color:Yellow;height:100px;"  实际将无法起作用。
<InputDatalist 只能使用css来注入样式；<InputDatalist css={{ 方式注入的样式，只能在...other占位替换位置接收样式， 而不能用参数style参数css类似这样的声明参数方式引入的样式。
但是若父辈采用React.cloneElement( React.Children.only(children),{style: {flex: '1 1 60%' } }这样模式，就能够注入style，而且是style参数获得的声明参数方式引入样式。
 */
export const InputDatalist: React.FunctionComponent<InputDatalistProps> = (
    {
        autoComplete, autoFocus, inputSize = "md",
        fullWidth=true,
        datalist=[],
        style,
        onListChange,
        ...other
    }
) => {
    const { uid } = React.useContext(InputGroupContext);
    //这个版本：不需要React.forwardRef(()=>{})的，注入ref性能损失， {...safeBind({ ref }, other)}
    //这底下的 css={{  ...style ,位置必须放在最后一个， 否则...style可能被顺序排在后面的同样名字参数所覆盖。
    //但是无法修改弹出的列表的样式。 <datalist 无法设置样式，浏览器自动设置的样式。
    //死活都改不了； 弹出列表datalist无法自己定做样式。
    return (
        <div css={{
            textAlign: 'left',
            width: "100%",
            ...style
        }}
        >
            <datalist id={`list${uid}`}>
                { datalist.map((one,i) => {
                    return <option key={i} value={one} />;
                }) }
            </datalist>
            <InputBase inputSize={inputSize}
                       css={[
                           { display: "inline-block" },
                           //width:  children? "70%" : '100%',
                           !fullWidth &&{
                               width: 'unset'
                           }
                       ]}
                       {...other}
                       list={`list${uid}`}
                       onSave={txt=> onListChange(txt)}
                //onSave={e => onListChange( e.currentTarget.value||undefined ) }
            />
        </div>
    );
};


const getSwitchHeight = (size: ButtonSize) => {
    if (size === "xs") return 16;
    else if (size === "sm") return 22;
    else if (size === "lg") return 36;
    else if (size === "xl") return 44;
    else return 28;
};

export interface CheckSwitchProps
    extends React.InputHTMLAttributes<HTMLInputElement> {
    // topDivStyle?: SerializedStyles;
    /** The size of the Switch. 多大高度方向的尺寸 */
    hsize?: ButtonSize;
    checked: boolean;
    onChange: (e: any)=> void;
}

/**
 * 从‘react-switch’导入组件,做个可替代Check的更加美观的开关组件。
 * @param disabled
 * @param topDivStyle
 */
export const CheckSwitch: React.FunctionComponent<CheckSwitchProps> = ({
                                                                           id,
                                                                           disabled,
                                                                           style,
                                                                           checked,
                                                                           onChange,
                                                                           hsize = "md" as ButtonSize,
                                                                           ...other
                                                                       }) => {
    const { uid } = React.useContext(InputGroupContext);
    //不能用这个React.useCallback((checked,event,id) => {， 状态无法切换, 外面传递进来的onChange()还是旧的数据，无法更新成新数值。
    //onHandleChange用了 useCallback（,[]）: 就是捕获函数， onChange就无法变化了,所以被锁住更新。
    const onHandleChange = (checked: boolean,
                            event: React.SyntheticEvent<MouseEvent | KeyboardEvent> | MouseEvent,
                            id: string ) => {
        onChange(event);
    };



    return (
        <div  className="Switch"
              css={
                  {
                      //display: "flex",  若加上这"flex",导致textAlign会失去作用了。
                      alignItems: "center",
                      textAlign: 'left',
                      ...style
                  }
              }
              {...other}
        >
            <Switch id={uid}
                    checked={checked}
                    onChange={onHandleChange}
                    disabled={disabled}
                    height={getSwitchHeight(hsize)}
                    width={getSwitchHeight(hsize)*2}
            />
        </div>
    );
};

CheckSwitch.propTypes = {
    id: PropTypes.string,
    disabled: PropTypes.bool,
    hsize: PropTypes.oneOf(["xs", "sm", "md", "lg", "xl"])
};


//测试
function checkParent(parent: Element | null) {
    if (!parent) {
        console.error(new Error('empty parent element'))
        return
    }

    switch (parent.tagName) {
        case 'area':
        case 'base':
        case 'br':
        case 'col':
        case 'embed':
        case 'hr':
        case 'img':
        case 'input':
        case 'keygen':
        case 'link':
        case 'menuitem':
        case 'meta':
        case 'param':
        case 'source':
        case 'track':
        case 'wbr':
        case 'script':
        case 'style':
        case 'textarea':
        case 'title':
            console.error(
                new Error(
                    'Unsupported parent tag name ' +
                    parent.tagName.toLowerCase() +
                    '.' +
                    parent.className.replace(/\s+/, '.') +
                    ' . Change the tag or wrap it in a supported tag(e.g. div).'
                )
            )
    }

    const parentStyles = window.getComputedStyle(parent)
    if (parentStyles && parentStyles.getPropertyValue('position') === 'static') {
        console.warn(
            new Error(
                'LineColumn: ' +
                "The 'position' CSS property of element " +
                parent.tagName.toLowerCase() +
                '.' +
                parent.className.replace(/\s+/, '.') +
                " should not be 'static'."
            )
        )
    }
}

const ENTER_KEY_CODE = 13;
const ESC_KEY_CODE = 27;
export interface CommitInputProps  extends InputBaseProps {
    fullWidth?: boolean;
    //noSaveBlur?: boolean;  不是一回事 //失去焦点也不需要保存=属于输入框之外上层组件外部事件
    //保存触发后是否要清空编辑内容
    reset?: boolean;
    value?: string | number;
    //使用如onSave={(text)=> {set编号(text);}}来代替onChange={e =>set编号( e.currentTarget.value||undefined ) }
    onSave: (text: string) => void;
}
/**
 * CommitInput 比起 Input多出触发控制，编辑完成后提交修改的回调函数。
 * 可大幅度提高性能，用户输入字符顺畅了。避免onChange单个字符单个字符地触发value变化了，从而Input上级组件会重做render，性能就变差。
 * [特别注意！] 很可能直接就点击提交按钮，没经过onBlur()，必须外部额外的机制来确保输入的保存。比如提交按钮<Button>改成如下的：
 *      <ButtonRefComp  ref={commitBlurRef}
 *              onPointerOver={e=> { commitBlurRef!.current!.focus() }}
 *      Save Me! </ButtonRefComp>
 * 您也可以直接添加一个修改确认按钮，多一道用户点击按钮操作，来确保CommitInput已修改内容的保存。
 * InputBase组件没有reset参数的；
 */
export const CommitInput: React.FunctionComponent<CommitInputProps> =
    (
        {
            autoComplete, autoFocus,
            inputSize = "md",
            fullWidth=true,
            style,
            value,
            reset=false,
            onSave,
            ...other
        }
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        //内部的，一次性倒腾value
        const commitChanges = (e :any) => {
            //const newText = typeof text === "string" ? text.trim() : text;  前后的空格，不能换行的。
            if (e.target.value !== value) {
                onSave(e.target.value as any);   //真正的目的终点：触发修改类容的回调。 +退出编辑状态；
                if(reset)
                    e.target.value= "";
            }
        };

        //触摸屏手机，没有搞ENTER_KEY_CODE触发，替代回车按键。
        //手机触摸屏：触发时机太迟了；保存按钮点击过后才会触发onBlur()；必须要有一个提前机制。
        const handleBlur = (e :any) => {
            commitChanges(e);   //焦点丧失掉的触发。
        };

        const handleKeyDown = (e :any) => {
            if (e.keyCode === ENTER_KEY_CODE) {
                commitChanges(e);
            }
            else if (e.keyCode === ESC_KEY_CODE) {
                e.target.value= value;  //手机无法触发ESC的按键类似功能!
            }
        };

        return (
            <div  css={{
                textAlign: 'left',
                width: "100%",
                ...style
            }}
            >
                <input
                    id={uid}
                    className="Input"
                    autoComplete={autoComplete}
                    autoFocus={autoFocus}
                    {...bind}
                    css={[
                        baseStyles,
                        inputSizes[inputSize],
                        active && activeBackground,
                        error && errorStyles,
                        { height },
                        !fullWidth &&{
                            width: 'unset',
                        },
                    ]}
                    defaultValue={value}
                    onBlur={handleBlur}
                    onKeyDown={handleKeyDown}
                    {...other}
                />
            </div>
        );
    };

export interface WordTriggerInputProps  extends InputBaseProps {
    fullWidth?: boolean;
    value?: string | number;
    //使用如onSave={(text)=> {set编号(text);}}来代替onChange={e =>set编号( e.currentTarget.value||undefined ) }
    onSave: (text: string) => void;
    //每次触发完成后，后台fetchdata(),+Suspense,之后导致编辑框WordTriggerInput失去焦点了。refetchResult是数据，每次fetchdata的结果。
    refetchResult?: any;    //仅仅用作useEffect依赖项。用于重新找回焦点，才能在中文输入法状态下继续输入。
    //有时候需要用一个变量传递给两个输入Input组件。
    //两个编辑框数据关联的特殊情况： 如何确保把另一个输入框的内容复制过来，还不会因为reftech焦点丧失handleBlur()后数据保持一致。
}
/**
 * WordTriggerInput 比起 Input能够支持非ASCII码的输入法模式下的单词或者多个汉字一次性触发更新,不像Input每次Key事件都会提交变更的。
 * CommitInput是用户确认输入一整个短语字符串后明确确认了才会提交修改的。
 * Input在每个KeyDown都会提交的，导致React.Suspense+重新获取搜索索引列表的应用场景下中文输入法是无法完成正常输入的。
 * [限制条件!] 比起其它Input,这个WordTriggerInput引发焦点征用,[value,onSave]组合的状态提供方不能共享同一个的(引发死循环),必须要独立设置状态。
 */
export const WordTriggerInput: React.FunctionComponent<WordTriggerInputProps> =
    (
        {
            autoComplete, autoFocus,
            inputSize = "md",
            fullWidth=true,
            style,
            value,
            onSave,
            refetchResult,
            ...other
        }
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        //手机输入法可以做到英文的多个字符的一次性触发， 电脑上英文输入只能单个字符就要触发提交,用中文输入法可以达成多个字符一次提交。这和输入法相关。
        //数字输入都只能单个单个的数字触发。
        const [imeLock, setImeLock] = React.useState(false);
        //不是英文字符
        function isKorean(text : any) {
            const reg = /([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi;
            return reg.test(text);
        }
        const handleCompositionStart= ()=> {
            setImeLock(true);
        }
        const handleCompositionEnd= (e : any) =>{
            if (imeLock) {
                setImeLock(false);
                onSave(e.target.value);
            }
        }
        const handleCompositionUpdate= (e : any)=> {
            const text = e.target.value;
            const lastCharacter = text[text.length - 1] || '';
            setImeLock(!isKorean(lastCharacter));
        }
        const handleKeyUp= (e : any)=> {
            if (!imeLock) {
                onSave(e.target.value)
            }
        }
        const handleBlur = (e :any) => {
            if (e.target.value !== value) {
                onSave(e.target.value)
            }
        };
        const handleFocus = (e :any) => {
            if(e.target.value !== value){
                e.target.value = value;
            }
        };
        //只需要处理搜索框背后叉号被点击情况：点击叉号清空。
        const handleChange = (e :any) => {
            //onSave(e.target.value) 全都触发保存，焦点失去再抓回来，无法输入中文 输入法了。
            if(e.target.value === "" ){
                onSave(e.target.value)
            }
        };
        const focusRef = React.useRef<HTMLDivElement | null>(null);
        //特殊依赖项！ 若refetchResult已经变动了？说明Suspense获取数据已经完成了，重新进入显示本组件。
        useEffect( () => {
                focusRef!.current!.focus();
            },
            [refetchResult]
        );

        return (
            <div  css={{
                textAlign: 'left',
                width: "100%",
                ...style
            }}
            >
                <input
                    id={uid}
                    className="Input"
                    autoComplete={autoComplete}
                    autoFocus={autoFocus}
                    {...bind}
                    css={[
                        baseStyles,
                        inputSizes[inputSize],
                        active && activeBackground,
                        error && errorStyles,
                        { height },
                        !fullWidth &&{
                            width: 'unset',
                        },
                    ]}
                    defaultValue={value}
                    onCompositionStart={handleCompositionStart}
                    onCompositionEnd={handleCompositionEnd}
                    onCompositionUpdate={handleCompositionUpdate}
                    onKeyUp={handleKeyUp}
                    onChange={handleChange}
                    onBlur={handleBlur}
                    onFocus={handleFocus}
                    ref={focusRef as any}
                    {...other}
                />
            </div>
        );
    };

export interface BlurTriggerRefInputProps
    extends React.InputHTMLAttributes<HTMLInputElement> {
    /** The size of the input element */
    inputSize?: InputSize;
    //topDivStyle?: SerializedStyles;
    value?: string | number;
    onSave: (text: string) => void;
    //组合框输入的 向关联的列表；onBlur要排除点击列表的情况
    needTrig?: (e :any) => boolean;
    //datlistRef?: React.RefObject<HTMLElement>;  //React.Ref<any>;
}

/**InputBase的变种{传递 ref }版本：目前用于ComboBoxDatalist内部的，失去焦点触发机制。
 * 回调过滤needTrig； 而参数onSave用于触发Blur回调。
 *本组件用于有参数 value={query} onChange={onInputChange} 情形；
 *本组件若是设置有 onChange(),onFocus，直接从other接纳走了，透传下去给input；
 *但是我这里已经有onBlur和onKeyDown了，若是外部强制传入onBlur或onKeyDown的就要依次合并触发执行啊。
 */
export const BlurTriggerRefInput = React.forwardRef(
    (
        { autoComplete, autoFocus, inputSize = "md",
            value,needTrig, onSave,
            onBlur, onKeyDown,
            ...other
        }: BlurTriggerRefInputProps,
        ref: React.Ref<HTMLInputElement>
    ) => {
        const { uid, error } = React.useContext(InputGroupContext);
        const { bind, active } = useActiveStyle();
        const {
            baseStyles,
            inputSizes,
            activeBackground,
            errorStyles
        } = useSharedStyle();
        const height = getHeight(inputSize);
        const commitChanges = (e :any) => {
            //已经是query的单个字符onChange模式了，if (e.target.value !== value) {肯定成立。
            onSave(e.target.value as any);    //我要保存的是最外面组件的变量，不是内部临时变量。
        };
        const handleBlur = (e :any) => {
            if( !needTrig  || ( needTrig && needTrig(e) ) )
                commitChanges(e);
            onBlur && onBlur(e);
        };
        const handleKeyDown = (e :any) => {
            if (e.keyCode === ENTER_KEY_CODE) {
                commitChanges(e);
            }
            else if (e.keyCode === ESC_KEY_CODE) {
                //非调试就不起作用; ESC不好使 因为onChange 已经修改 value变量了。
                e.target.value= value;
            }
            onKeyDown && onKeyDown(e);
        };
        return (
            <input
                id={uid}
                className="Input"
                autoComplete={autoComplete}
                autoFocus={autoFocus}
                {...bind}
                css={[
                    baseStyles,
                    inputSizes[inputSize],
                    active && activeBackground,
                    error && errorStyles,
                    { height }
                ]}
                //defaultValue={value}
                value={value}
                onBlur={handleBlur}
                onKeyDown={handleKeyDown}
                {...safeBind({ ref }, other)}
            />
        );
    }
);

